﻿// -------------------------------------------------------------------------
//    @FileName         :    NFSecurity.h
//    @Author           :    gaoyi
//    @Date             :    24-8-1
//    @Email            :    445267987@qq.com
//    @Module           :    NFSecurity
//
// -------------------------------------------------------------------------

#pragma once

#include "NFComm/NFCore/NFPlatform.h"

#include <cryptopp/aes.h>
#include <cryptopp/dh.h>
#include <cryptopp/filters.h>
#include <cryptopp/integer.h>
#include <cryptopp/modes.h>
#include <cryptopp/nbtheory.h>
#include <cryptopp/osrng.h>
#include <cryptopp/secblock.h>
#include "proto_client2access.pb.h"

class NFSecurity
{
public:
    NFSecurity();

    virtual ~NFSecurity();
public:
    void InitClient();
    void InitServer();
    void Init(const CryptoPP::Integer& publicKey, const CryptoPP::Integer& privateKey);
public:
    // 传入对方的dh公钥，生成aes加密对象
    bool init_aes( const char* other_dhpubkey, size_t key_size );

    // 加密
    void aes_encrypt( const std::string& plain_text, std::string& cipher_text );

    // 解密
    void aes_decrypt( const std::string& cipher_text, std::string& plain_text );

    void aes_encrypt( const char* plain_text, size_t length, std::string& cipher_text );

    // 解密
    void aes_decrypt( const char* cipher_text, size_t length, std::string& plain_text );

    void dump_secbyteblock( const std::string& name, CryptoPP::SecByteBlock* block );

    bool package_compress_encrypt( proto_client2access::Proto_C2ACompressType compress_type,
        proto_client2access::Proto_C2AEncryptType encrypt_type,
        const std::string& input,
        std::string& output );

public:
    CryptoPP::DH m_client_dh;                   // 交换秘钥
    CryptoPP::SecByteBlock* m_client_dh_pubKey; // 交换秘钥公钥，发送给对方
    CryptoPP::SecByteBlock* m_client_dh_priKey; // 交换秘钥私钥

    // 使用CFB模式，不需要补块
    uint8_t m_iv[ CryptoPP::AES::BLOCKSIZE ];
    CryptoPP::CFB_Mode< CryptoPP::AES >::Encryption* m_aes_encrypt; // aes加密对象
    CryptoPP::CFB_Mode< CryptoPP::AES >::Decryption* m_aes_decrypt; // aes解密对象

private:
    // 交换秘钥使用的p、g（懒加载方式，避免静态初始化顺序问题）
    static const CryptoPP::Integer& GetDhP();
    static const CryptoPP::Integer& GetDhG();
    static const CryptoPP::Integer& GetServerDhP();
    static const CryptoPP::Integer& GetServerDhG();
};